﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using System.Threading;

namespace NewDevice
{
    /// <summary>
    /// 使用内存映射的无锁实现（高性能）
    /// </summary>
    public class LockFreeBoolArray
    {
        private readonly int[] _values; // 使用int数组，每个int存储32个bool
        private readonly int _size;
        private readonly int _arraySize;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="size"></param>
        /// <exception cref="ArgumentException"></exception>
        public LockFreeBoolArray(int size)
        {
            if (size <= 0)
                throw new ArgumentException("大小必须大于0", nameof(size));

            _size = size;
            _arraySize = (size + 31) / 32; // 计算需要的int数量
            _values = new int[_arraySize];
        }

        public int Size => _size;

        /// <summary>
        /// 无锁设置布尔值
        /// </summary>
        public void SetValue(int index, bool value)
        {
            if (index < 0 || index >= _size)
                throw new ArgumentOutOfRangeException(nameof(index));

            int arrayIndex = index / 32;
            int bitIndex = index % 32;
            int mask = 1 << bitIndex;

            SpinWait spinWait = new SpinWait();

            while (true)
            {
                int oldValue = Volatile.Read(ref _values[arrayIndex]);
                int newValue = value
                    ? (oldValue | mask)     // 设置位为1
                    : (oldValue & ~mask);   // 设置位为0

                int result = Interlocked.CompareExchange(ref _values[arrayIndex], newValue, oldValue);
                if (result == oldValue)
                    break; // 成功更新

                spinWait.SpinOnce();
            }
        }

        /// <summary>
        /// 无锁读取布尔值
        /// </summary>
        public bool GetValue(int index)
        {
            if (index < 0 || index >= _size)
                throw new ArgumentOutOfRangeException(nameof(index));

            int arrayIndex = index / 32;
            int bitIndex = index % 32;
            int mask = 1 << bitIndex;

            int value = Volatile.Read(ref _values[arrayIndex]);
            return (value & mask) != 0;
        }

        /// <summary>
        /// 原子性反转布尔值
        /// </summary>
        public bool ToggleValue(int index)
        {
            if (index < 0 || index >= _size)
                throw new ArgumentOutOfRangeException(nameof(index));

            int arrayIndex = index / 32;
            int bitIndex = index % 32;
            int mask = 1 << bitIndex;

            SpinWait spinWait = new SpinWait();

            while (true)
            {
                int oldValue = Volatile.Read(ref _values[arrayIndex]);
                int newValue = oldValue ^ mask; // 异或操作反转特定位

                int result = Interlocked.CompareExchange(ref _values[arrayIndex], newValue, oldValue);
                if (result == oldValue)
                    return (newValue & mask) != 0; // 返回新值

                spinWait.SpinOnce();
            }
        }

        /// <summary>
        /// 获取所有值的快照（非原子性，但一致性较好）
        /// </summary>
        public bool[] GetSnapshot()
        {
            bool[] snapshot = new bool[_size];

            // 快速读取所有值
            for (int i = 0; i < _size; i++)
            {
                snapshot[i] = GetValue(i);
            }

            return snapshot;
        }
    }
}